﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CdcSoftware.Pivotal.Applications.Core.Client;
using CdcSoftware.Pivotal.Engine.UI.Forms;
using System.Windows.Forms;
using System.Security.Cryptography;
using CdcSoftware.Pivotal.Engine.Client.Services.Interfaces;
using System.Data;
using CdcSoftware.Pivotal.Engine.Types.Database;
using CdcSoftware.Pivotal.Engine.Types.MailMerges;
using CdcSoftware.Pivotal.Engine;
using CdcSoftware.Pivotal.Applications.Core.Common;

namespace Pcm.Retail.Client.FormTasks
{
    public partial class RE_Staff : FormClientTask
    {
        /// <summary>
        /// Send the system generated pass info through email.
        /// </summary>
        /// <param name="sender">The control associated with the event triggered</param>
        /// <param name="args">The argument for the event</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.8.1     2011-05-27      DS          Initial version for Retail.
        /// </history>
        public virtual void OnClickResetPassword(object sender, EventArgs args)
        {
            try
            {
                if (this.RecordId != null)
                {
                    string password = GenerateRandomPassword(8, 8);

                    this.PrimaryDataRow["Password_"] = Globals.Encrypt(password);
                    this.PrimaryDataRow["Resetted_Password"] = password;
                    this.PrimaryDataRow["Prompt_To_Reset"] = true;

                    //Save the record.
                    this.SaveRecord();
                    this.LoadRecord();

                    //Email the staff with the new password.LE Name: "RE_Staff Password reset mail." 
                    this.SystemClient.ExecuteServerTask("Re_Staff", "ResetPassInfoEmail",new Type[]{typeof(string),typeof(string),typeof(Id)}, new object[] { "RE_Staff Password reset mail.", "Reset password successful", this.RecordId });
                }
                else
                {
                    PivotalMessageBox.Show("Please save the record before resetting the passowrd.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception ex)
            {
                Globals.HandleException(ex, true);
            }
        }

        /// <summary>
        /// On Enter press on field Mobile move to the next field.
        /// </summary>
        /// <param name="minLength">Password minimum length.</param>
        /// <param name="maxLength">Password maximum length.</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.8.1     2011-05-27      DS          Initial version for Retail.
        /// </history>
        private static string GenerateRandomPassword(int minLength, int maxLength)
        {
            char[] password = null;
            int nextCharIdx = 0;
            int nextGroupIdx = 0;
            int nextLeftGroupsOrderIdx = 0;
            int lastCharIdx = 0;
            int seed = 0;
            char[][] charGroups;
            int[] charsLeftInGroup;
            byte[] randomBytes = new byte[4];

            charGroups = new char[][]{"abcdefgijkmnopqrstwxyz".ToCharArray(),"ABCDEFGHJKLMNPQRSTWXYZ".ToCharArray(), "23456789".ToCharArray(),"!@#$%&*".ToCharArray()};
            charsLeftInGroup = new int[charGroups.Length];

            for (int i = 0; i < charsLeftInGroup.Length; i++)
                charsLeftInGroup[i] = charGroups[i].Length;

            int[] leftGroupsOrder = new int[charGroups.Length];

            for (int i = 0; i < leftGroupsOrder.Length; i++)
                leftGroupsOrder[i] = i;

            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(randomBytes);
            seed = (randomBytes[0] & 0x7f) << 24 | randomBytes[1] << 16 | randomBytes[2] << 8 | randomBytes[3];
            Random random = new Random(seed);

            if (minLength < maxLength)
                password = new char[random.Next(minLength, maxLength + 1)];
            else
                password = new char[minLength];
            int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;

            for (int i = 0; i < password.Length; i++)
            {
                if (lastLeftGroupsOrderIdx == 0)
                    nextLeftGroupsOrderIdx = 0;
                else
                    nextLeftGroupsOrderIdx = random.Next(0, lastLeftGroupsOrderIdx);
                nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
                lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;

                if (lastCharIdx == 0)
                    nextCharIdx = 0;
                else
                    nextCharIdx = random.Next(0, lastCharIdx + 1);

                password[i] = charGroups[nextGroupIdx][nextCharIdx];

                if (lastCharIdx == 0)
                    charsLeftInGroup[nextGroupIdx] = charGroups[nextGroupIdx].Length;
                else
                {
                    if (lastCharIdx != nextCharIdx)
                    {
                        char temp = charGroups[nextGroupIdx][lastCharIdx];
                        charGroups[nextGroupIdx][lastCharIdx] = charGroups[nextGroupIdx][nextCharIdx];
                        charGroups[nextGroupIdx][nextCharIdx] = temp;
                    }
                    charsLeftInGroup[nextGroupIdx]--;
                }

                if (lastLeftGroupsOrderIdx == 0)
                {
                    lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
                }
                else
                {
                    if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
                    {
                        int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
                        leftGroupsOrder[lastLeftGroupsOrderIdx] = leftGroupsOrder[nextLeftGroupsOrderIdx];
                        leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
                    }
                    lastLeftGroupsOrderIdx--;
                }
            }
            return new string(password);
        }

        /// <summary>
        /// Copy "Login as in charge" and "Can authorize transactions" on exit of Job Title
        /// </summary>
        /// <param name="sender">The control associated with the event triggered</param>
        /// <param name="args">The argument for the event</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.8.2     2013-01-09      AS          Initial version
        /// </history>
        public virtual void OnExitJobTitle(object sender, EventArgs args)
        {
            try
            {
                DataTable jobTitleMapping = Globals.GetDataTable("RE_Job Title Mapping for LOB and JobTitle?", new object[] { this.PrimaryDataRow["LOB_Id"], this.PrimaryDataRow["Job_Title"] }, new string[] { });

                if (jobTitleMapping != null && jobTitleMapping.Rows.Count > 0)
                {
                    this.PrimaryDataRow["In_Charge"] = TypeConvert.ToBoolean(jobTitleMapping.Rows[0]["In_Charge"]);
                    this.PrimaryDataRow["Authorize"] = TypeConvert.ToBoolean(jobTitleMapping.Rows[0]["Authorization_"]);
                }
                else
                {
                    this.PrimaryDataRow["In_Charge"] = DBNull.Value;
                    this.PrimaryDataRow["Authorize"] = DBNull.Value;
                }
            }
            catch (Exception ex)
            {
                Globals.HandleException(ex, true);
            }
        }

        /// <summary>
        /// Copy "Login as in charge" and "Can authorize transactions" on exit of LOB
        /// </summary>
        /// <param name="sender">The control associated with the event triggered</param>
        /// <param name="args">The argument for the event</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.8.2     2013-01-09      AS          Initial version
        /// </history>
        public virtual void OnExitLOB(object sender, EventArgs args)
        {
            try
            {
                DataTable jobTitleMapping = Globals.GetDataTable("RE_Job Title Mapping for LOB and JobTitle?", new object[] { this.PrimaryDataRow["LOB_Id"], this.PrimaryDataRow["Job_Title"] }, new string[] { });

                if (jobTitleMapping != null && jobTitleMapping.Rows.Count > 0)
                {
                    this.PrimaryDataRow["In_Charge"] = TypeConvert.ToBoolean(jobTitleMapping.Rows[0]["In_Charge"]);
                    this.PrimaryDataRow["Authorize"] = TypeConvert.ToBoolean(jobTitleMapping.Rows[0]["Authorization_"]);
                }
                else
                {
                    this.PrimaryDataRow["In_Charge"] = DBNull.Value;
                    this.PrimaryDataRow["Authorize"] = DBNull.Value;
                }
            }
            catch (Exception ex)
            {
                Globals.HandleException(ex, true);
            }
        }
    }
}
